home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / linux-bo / comboot-.0 / comboot- / comboot-1.0 / comboot.S < prev    next >
Encoding:
Text File  |  1996-04-25  |  8.3 KB  |  400 lines

  1. !
  2. ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
  3. ! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current
  4. ! versions of linux which compress the kernel
  5. !
  6. SYSSIZE = 4096    ! 4096 * 16 bytes = 64kB maximum size of .COM file
  7.         ! If you know the size of the .COM file that you are booting,
  8.         ! You can reduce this number to (com_file_size+15)/16
  9. !    bootsect.s        Copyright (C) 1991, 1992 Linus Torvalds
  10. !    modified by Drew Eckhardt
  11. !    modified by Bruce Evans (bde)
  12. !
  13. ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
  14. ! itself out of the way to address 0x90000, and jumps there.
  15. !
  16. ! bde - should not jump blindly, there may be systems with only 512K low
  17. ! memory.  Use int 0x12 to get the top of memory, etc.
  18. !
  19. ! It then loads 'setup' directly after itself (0x90200), and the system
  20. ! at 0x10000, using BIOS interrupts. 
  21. !
  22. ! NOTE! currently system is at most (8*65536-4096) bytes long. This should 
  23. ! be no problem, even in the future. I want to keep it simple. This 508 kB
  24. ! kernel size should be enough, especially as this doesn't contain the
  25. ! buffer cache as in minix (and especially now that the kernel is 
  26. ! compressed :-)
  27. !
  28. ! The loader has been made as simple as possible, and continuous
  29. ! read errors will result in a unbreakable loop. Reboot by hand. It
  30. ! loads pretty fast by getting whole tracks at a time whenever possible.
  31.  
  32. .text
  33.  
  34. BOOTSEG   = 0x07C0            ! original address of boot-sector
  35.  
  36. ! These locations taken from <linux/config.h> in Linux 1.3.95 kernel.
  37. ! They are arbitrary and can be changed to other location in any unused
  38. ! part of the first 640kB of RAM.
  39. INITSEG      = 0x9000            ! we move boot here - out of the way
  40. SYSSEG      = 0x1000            ! system loaded at 0x10000 (65536).
  41.  
  42. !INITSEG   = DEF_INITSEG        ! we move boot here - out of the way
  43. !SYSSEG    = DEF_SYSSEG            ! system loaded at 0x10000 (65536).
  44.  
  45. ! ld86 requires an entry symbol. This may as well be the usual one.
  46. .globl    _main
  47. _main:
  48. #if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
  49.     int    3
  50. #endif
  51.     mov    ax,#BOOTSEG
  52.     mov    ds,ax
  53.     mov    ax,#INITSEG
  54.     mov    es,ax
  55.     mov    cx,#256
  56.     sub    si,si
  57.     sub    di,di
  58.     cld
  59.     rep
  60.     movsw
  61.  
  62.     jmpi    go,INITSEG
  63.  
  64. ! ax and es already contain INITSEG
  65.  
  66. go:    mov    di,#0x4000-12    ! 0x4000 is arbitrary value >= length of
  67.                 ! bootsect + length of setup + room for stack
  68.                 ! 12 is disk parm size
  69.  
  70. ! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
  71. ! wouldn't have to worry about this if we checked the top of memory.  Also
  72. ! my BIOS can be configured to put the wini drive tables in high memory
  73. ! instead of in the vector table.  The old stack might have clobbered the
  74. ! drive table.
  75.  
  76.     mov    ds,ax
  77.     mov    ss,ax        ! put stack at INITSEG:0x4000-12.
  78.     mov    sp,di
  79. /*
  80.  *    Many BIOS's default disk parameter tables will not 
  81.  *    recognize multi-sector reads beyond the maximum sector number
  82.  *    specified in the default diskette parameter tables - this may
  83.  *    mean 7 sectors in some cases.
  84.  *
  85.  *    Since single sector reads are slow and out of the question,
  86.  *    we must take care of this by creating new parameter tables
  87.  *    (for the first disk) in RAM.  We will set the maximum sector
  88.  *    count to 36 - the most we will encounter on an ED 2.88.  
  89.  *
  90.  *    High doesn't hurt.  Low does.
  91.  *
  92.  *    Segments are as follows: ds=es=ss=cs - INITSEG,
  93.  *        fs = 0, gs is unused.
  94.  */
  95.  
  96. ! cx contains 0 from rep movsw above
  97.  
  98.     mov    fs,cx
  99.     mov    bx,#0x78        ! fs:bx is parameter table address
  100.     push    ds
  101.     seg fs
  102.     lds    si,(bx)            ! ds:si is source
  103.  
  104.     mov    cl,#6            ! copy 12 bytes
  105.     cld
  106.     push    di
  107.  
  108.     rep
  109.     movsw
  110.  
  111.     pop    di
  112.     pop    ds
  113.  
  114.     movb    4(di),*36        ! patch sector count
  115.  
  116.     seg fs
  117.     mov    (bx),di
  118.     seg fs
  119.     mov    2(bx),es
  120.  
  121. ! Note that 'es' is already set up.
  122. ! Also cx is 0 from rep movsw above.
  123.  
  124.     xor    ah,ah            ! reset FDC 
  125.     xor    dl,dl
  126.     int     0x13    
  127.  
  128. ! Get disk drive parameters, specifically nr of sectors/track
  129.  
  130. #if 0
  131.  
  132. ! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
  133. ! disks.  It doesn't work for one of my BIOS's (1987 Award).  It was
  134. ! fatal not to check the error code.
  135.  
  136.     xor    dl,dl
  137.     mov    ah,#0x08        ! AH=8 is get drive parameters
  138.     int    0x13
  139.     xor    ch,ch
  140. #else
  141.  
  142. ! It seems that there is no BIOS call to get the number of sectors.  Guess
  143. ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
  144. ! 15 if sector 15 can be read.  Otherwise guess 9.
  145.  
  146.     mov    si,#disksizes        ! table of sizes to try
  147.  
  148. probe_loop:
  149.     lodsb
  150.     cbw                ! extend to word
  151.     mov    sectors, ax
  152.     cmp    si,#disksizes+4
  153.     jae    got_sectors        ! if all else fails, try 9
  154.     xchg    ax, cx            ! cx = track and sector
  155.     xor    dx, dx            ! drive 0, head 0
  156.     xor    bl, bl
  157.     mov    bh,#2            ! address after boot sector
  158.                     !   (512 bytes from origin, es = cs)
  159.     mov    ax,#0x0201        ! service 2, 1 sector
  160.     int    0x13
  161.     jc    probe_loop        ! try next value
  162.  
  163. #endif
  164.  
  165. got_sectors:
  166.  
  167. ! Restore es
  168.  
  169.     mov    ax,#INITSEG
  170.     mov    es,ax
  171.  
  172. ! Print some inane message
  173.  
  174.     mov    ah,#0x03        ! read cursor pos
  175.     xor    bh,bh
  176.     int    0x10
  177.     
  178.     mov    cx,#32
  179.     mov    bx,#0x0007        ! page 0, attribute 7 (normal)
  180.     mov    bp,#msg1
  181.     mov    ax,#0x1301        ! write string, move cursor
  182.     int    0x10
  183.  
  184. ! ok, we've written the message, now
  185. ! we want to load the system (at 0x10000)
  186.  
  187.     mov    ax,#SYSSEG
  188.     mov    es,ax        ! segment of 0x010000
  189.     call    read_it
  190.     call    kill_motor
  191.     call    print_nl
  192.  
  193. ! after that (everything loaded), we jump to
  194. ! the .COM file loaded directly after the bootblock:
  195.  
  196.     jmpi    0x100,SYSSEG-0x10    ! A .com file expects to be offset
  197.                     ! by 0x100 from the beginning of
  198.                     ! its code segment.
  199.  
  200. ! This routine loads the system at address 0x10000, making sure
  201. ! no 64kB boundaries are crossed. We try to load it as fast as
  202. ! possible, loading whole tracks whenever we can.
  203. !
  204. ! in:    es - starting address segment (normally 0x1000)
  205. !
  206. sread:    .word 0            ! sectors read of current track
  207. head:    .word 0            ! current head
  208. track:    .word 0            ! current track
  209.  
  210. read_it:
  211.     mov    al,#1
  212.     mov    sread,al
  213.     mov ax,es
  214.     test ax,#0x0fff
  215. die:    jne die            ! es must be at 64kB boundary
  216.     xor bx,bx        ! bx is starting address within segment
  217. rp_read:
  218. #ifdef __BIG_KERNEL__
  219. #define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
  220.                 ! NOTE: as86 can't assemble this
  221.     CALL_HIGHLOAD_KLUDGE    ! this is within setup.S
  222. #else
  223.     mov ax,es
  224.     sub ax,#SYSSEG
  225. #endif
  226.     cmp ax,#SYSSIZE        ! have we loaded all yet?
  227.     jbe ok1_read
  228.     ret
  229. ok1_read:
  230.     mov ax,sectors
  231.     sub ax,sread
  232.     mov cx,ax
  233.     shl cx,#9
  234.     add cx,bx
  235.     jnc ok2_read
  236.     je ok2_read
  237.     xor ax,ax
  238.     sub ax,bx
  239.     shr ax,#9
  240. ok2_read:
  241.     call read_track
  242.     mov cx,ax
  243.     add ax,sread
  244.     cmp ax,sectors
  245.     jne ok3_read
  246.     mov ax,#1
  247.     sub ax,head
  248.     jne ok4_read
  249.     inc track
  250. ok4_read:
  251.     mov head,ax
  252.     xor ax,ax
  253. ok3_read:
  254.     mov sread,ax
  255.     shl cx,#9
  256.     add bx,cx
  257.     jnc rp_read
  258.     mov ax,es
  259.     add ah,#0x10
  260.     mov es,ax
  261.     xor bx,bx
  262.     jmp rp_read
  263.  
  264. read_track:
  265.     pusha
  266.     pusha    
  267.     mov    ax, #0xe2e     ! loading... message 2e = .
  268.     mov    bx, #7
  269.      int    0x10
  270.     popa        
  271.  
  272.     mov    dx,track
  273.     mov    cx,sread
  274.     inc    cx
  275.     mov    ch,dl
  276.     mov    dx,head
  277.     mov    dh,dl
  278.     and    dx,#0x0100
  279.     mov    ah,#2
  280.     
  281.     push    dx                ! save for error dump
  282.     push    cx
  283.     push    bx
  284.     push    ax
  285.  
  286.     int    0x13
  287.     jc    bad_rt
  288.     add    sp, #8
  289.     popa
  290.     ret
  291.  
  292. bad_rt:    push    ax                ! save error code
  293.     call    print_all            ! ah = error, al = read
  294.     
  295.     
  296.     xor ah,ah
  297.     xor dl,dl
  298.     int 0x13
  299.     
  300.  
  301.     add    sp, #10
  302.     popa    
  303.     jmp read_track
  304.  
  305. /*
  306.  *    print_all is for debugging purposes.  
  307.  *    It will print out all of the registers.  The assumption is that this is
  308.  *    called from a routine, with a stack frame like
  309.  *    dx 
  310.  *    cx
  311.  *    bx
  312.  *    ax
  313.  *    error
  314.  *    ret <- sp
  315.  *
  316. */
  317.  
  318. print_all:
  319.     mov    cx, #5        ! error code + 4 registers
  320.     mov    bp, sp    
  321.  
  322. print_loop:
  323.     push    cx        ! save count left
  324.     call    print_nl    ! nl for readability
  325.  
  326.     cmp    cl, #5
  327.     jae    no_reg        ! see if register name is needed
  328.     
  329.     mov    ax, #0xe05 + 'A - 1
  330.     sub    al, cl
  331.     int    0x10
  332.  
  333.     mov    al, #'X
  334.     int    0x10
  335.  
  336.     mov    al, #':
  337.     int    0x10
  338.  
  339. no_reg:
  340.     add    bp, #2        ! next register
  341.     call    print_hex    ! print it
  342.     pop    cx
  343.     loop    print_loop
  344.     ret
  345.  
  346. print_nl:
  347.     mov    ax, #0xe0d    ! CR
  348.     int    0x10
  349.     mov    al, #0xa    ! LF
  350.     int     0x10
  351.     ret
  352.  
  353. /*
  354.  *    print_hex is for debugging purposes, and prints the word
  355.  *    pointed to by ss:bp in hexadecimal.
  356. */
  357.  
  358. print_hex:
  359.     mov    cx, #4        ! 4 hex digits
  360.     mov    dx, (bp)    ! load word into dx
  361. print_digit:
  362.     rol    dx, #4        ! rotate so that lowest 4 bits are used
  363.     mov    ax, #0xe0f    ! ah = request, al = mask for nybble
  364.     and    al, dl
  365.     add    al, #0x90    ! convert al to ascii hex (four instructions)
  366.     daa
  367.     adc    al, #0x40
  368.     daa
  369.     int    0x10
  370.     loop    print_digit
  371.     ret
  372.  
  373.  
  374. /*
  375.  * This procedure turns off the floppy drive motor, so
  376.  * that we enter the kernel in a known state, and
  377.  * don't have to worry about it later.
  378.  */
  379. kill_motor:
  380.     push dx
  381.     mov dx,#0x3f2
  382.     xor al, al
  383.     outb
  384.     pop dx
  385.     ret
  386.  
  387. sectors:
  388.     .word 0
  389.  
  390. disksizes:
  391.     .byte 36,18,15,9
  392.  
  393. msg1:
  394.     .byte 13,10
  395.     .ascii "Loading .COM image from floppy"
  396.  
  397. .org 510
  398. boot_flag:
  399.     .word 0xAA55
  400.